<?php

namespace System\library\url;

use System\library\Tools;
use System\library\config\Config;

/**
 * <b>Class</b> :        Rewriting<br>
 * <b>Fonction</b> :     Permet de generer la réécriture d'url
 * <br>
 * @version              1.0
 * @author               Dread <dreadlokeur@gmail.com>
 * @license              Licence publique générale GNU http://www.gnu.org/licenses/gpl.html
 * @copyright            Copyright 2011 - MidichloriansPHP and contributors
 * @package              System
 * @subpackage           library\url
 */
class Rewriting {

    /**
     * L'attribut qui permet de stocker les regles définis dans le .htaccess
     *
     * @access private
     * @var <array>
     */
    private $_rules = array();
    /**
     * L'attribut qui permet de définir si l'url est une url controller
     *
     * @access private
     * @var <bool>
     */
    private $_is_controller_url = false;
    /**
     * L'attribut qui permet de stocker le fichier vers lequel pointe l'url
     *
     * @access private
     * @var <string>
     */
    private $_url_file;
    /**
     * L'attribut qui permet de stocker le controller vers lequel pointe l'url
     *
     * @access private
     * @var <string>
     */
    private $_url_controller;
    /**
     * L'attribut qui permet de stocker laction vers laquelle pointe l'url
     *
     * @access private
     * @var <string>
     */
    private $_url_action;
    /**
     * L'attribut qui permet de stocker si l'url à été paramètrée
     *
     * @access private
     * @var <string>
     */
    private $_url_parameterized = false;
    /**
     * L'attribut qui permet de stocker les arguments de l'url
     *
     * @access private
     * @var <array>
     */
    private $_url_args = array();
    /**
     * L'attribut qui permet de stocker l'url generée
     *
     * @access private
     * @var <string>
     */
    private $_url;

    /**
     * Constructueur: permet de vérifier la présence et validité du .htaccess, pour ensuite recuperer la liste des rules définis dans ce dernier, afin de les stocker dans l'attribut "rules"
     *
     * @access public
     * @return <void>
     *
     * @see Config
     * @see MyException
     */
    public function __construct() {
        //On vérifie que le mod_rewrite d'apache est activé
        if (!in_array('mod_rewrite', apache_get_modules()))
            throw new \Exception('Impossible de génerer la réecritue d\'url car le mod_rewrite n\'est pas activé sur le serveur apache');
        // On vérifie la présence du fichier de configurations des regles de réécriture: htaccess
        if (!is_file(Config::getCons('PATH_PUBLIC') . '.htaccess') || !file_exists(Config::getCons('PATH_PUBLIC') . '.htaccess') || !is_readable(Config::getCons('PATH_PUBLIC') . '.htaccess'))
            throw new \Exception('Le fichier ".htaccess" est manquant ou invalid');

        //On ouvre le htaccess afin de recuperer toutes les rules de réecriture définis
        $handle = fopen(Config::getCons('PATH_PUBLIC') . '.htaccess', 'r');
        while (!feof($handle)) {
            $line = fgets($handle);
            if (strpos($line, 'RewriteRule') !== false)
                $this->_rules[] = $line;
        }
        fclose($handle);
    }

    /**
     * Constructueur: permet de spécifier si l'url sera une url controller ou non
     *
     * @access public
     * @param <bool> $value: true or false: est une url controller ou non
     * @return <void>
     *
     * @see MyException
     */
    public function setIsControllerUrl($value) {
        if (!is_bool($value))
            throw new \Exception('Impossible de définir si l\'url est un url controller, car la valeur n\'est pas un boolean');

        $this->_is_controller_url = $value;
    }

    /**
     * Permet d'etablir les paramètres à définir pour la récriture de l'url: fichier, spécifié le controller et l'action (optionnel)
     *
     * @access public
     * @param <string> $file: le fichier vers lequel l'url pointera
     * @param <string> $controller: le controller vers lequel l'url pointera (option)
     * @param <string> $controller: l'action vers laquelle l'url pointera (option)
     * @return <void>
     *
     * @see MyException
     */
    public function setUrlParams($file, $controller = false, $action = false) {
        if (!is_string($file))
            throw new \Exception('Impossible d\'etablir le paramètre "file" de l\'url, le format est incorrect, le format autorisé est string');
        $this->_url_file = $file;
        if ($controller) {
            if (!is_string($controller))
                throw new \Exception('Impossible d\'etablir le paramètre "controller" de l\'url, le format est incorrect, le format autorisé est string');
            $this->_url_controller = $controller;
        }
        if ($action)
            if (!is_string($action))
                throw new \Exception('Impossible d\'etablir le paramètre "action" de l\'url, le format est incorrect, le format autorisé est string');
        $this->_url_action = $action;
        $this->_url_parameterized = true;
    }

    /**
     * Permet d'etablir les arguments à définir dans l'url ?key=value
     *
     * @access public
     * @param <array> $args: les arguments de l'url, sous forme d'array: array('key' => 'value') passe en arguments à l'url key-value
     * @return <void>
     *
     * @see MyException
     */
    public function setUrlArgs($args) {
        if (!is_array($args))
            throw new \Exception('Impossible d\'etablir les arguments de l\'url, le format est incorrect, le format autorisé est array');
        $this->_url_args = $args;
    }

    /**
     * Permet de generer l'url réécrite en fonction de ses paramètres et arguments au préalable définis
     *
     * @access public
     * @return <string> $this->url: l'url généree
     *
     * @see MyException
     * @see Utils
     */
    public function getUrl() {
        if (!$this->_url_parameterized)
            throw new \Exception('L\'url n\'a pas été correctemet configurée');

        if ($this->_is_controller_url) {
            if ($this->_url_args) {
                $this->_url_file .= '/' . Tools::stringToUrl($this->_url_controller) . '/' . Tools::stringToUrl($this->_url_action) . '/';
                foreach ($this->_url_args as $k => $v) {
                    $this->_url_file .= Tools::stringToUrl($k) . '-' . Tools::stringToUrl($v) . '-';
                }
                $this->_url = trim($this->_url_file, '-') . '.html';
            }else
                $this->_url = $this->_url_file . '/' . Tools::stringToUrl($this->_url_controller) . '/' . Tools::stringToUrl($this->_url_action) . '.html';
        } else {
            if ($this->_url_args) {
                foreach ($this->_url_args as $k => $v)
                    $this->_url_file .= '-' . Tools::stringToUrl($k) . '-' . Tools::stringToUrl($v);

                $this->_url = $this->_url_file . '.html';
            }else
                $this->_url = $this->_url_file . '.html';
        }
        $this->_checkRewritingRule();
        if (!$this->_url)
            throw new \Exception('L\'url n\'a pas pu être générée');
        return Config::getCons('SITE_URL') . 'public/'. $this->_url;
    }

    /**
     * Permet de verifier qu'une url generé à une regle définis et valid dans la liste des regles du htaccess
     *
     * @access private
     * @return <void>
     *
     * @see MyException
     * @see Utils
     */
    private function _checkRewritingRule() {
        foreach ($this->_rules as $value) {
            if (preg_match('#' . Tools::selectStringByDelimiter($value, '^', '$') . '#', $this->_url)) {
                $good_rule = true;
                break;
            }
        }
        if (!isset($good_rule))
            throw new \Exception('Impossiblie de generer le l\'url: "' . $this->_url . ' ", la règle de réecriture n\'existe pas');
    }

}

?>
